package io.renren.modules.base.service.impl;

import io.netty.util.internal.StringUtil;
import io.renren.common.utils.R;
import io.renren.modules.base.controller.UploadFilesController;
import io.renren.modules.base.service.UploadFileService;
import io.renren.modules.base.utils.ConfigParamUtil;
import io.renren.modules.base.utils.ImageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;

@Service
public class UploadFileServiceImpl implements UploadFileService {

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");

    private static final String[] IMGTYPE = {"jpg", "jpeg", "png", "bmp"};

    private static final Logger log = LoggerFactory.getLogger(UploadFilesController.class);

    @Autowired
    private ConfigParamUtil configParamUtil;


    @Override
    public String uploadFile(MultipartFile file, String typePath) {
        String urlPath = "";
        try {
                // Get the file and save it somewhere
                urlPath = saveFile(file, typePath);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return urlPath;
    }

    @Override
    public List<String> uploadFiles(List<MultipartFile> files, String typePath) {
        List<String> list = new ArrayList<>();
        try {
            for (MultipartFile file: files) {
                list.add(saveFile(file, typePath));
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;    //2018年9月22日 20:19:03
        }
        return list;
    }

    @Override
    public String uploadFilesToString(List<MultipartFile> files, String typePath) {
        StringBuilder sb = new StringBuilder();
        try {
            for (MultipartFile file: files) {
                sb.append(saveFile(file, typePath));
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;    //2018年9月22日 20:19:03
        }
        sb.substring(0,sb.length()-1);
        return sb.toString();
    }

    @Override
    public R compressedUpload(List<MultipartFile> files, Double widthRate, Double heightRate) {
        //判断参数
        if ((!isDouble(widthRate.toString()) || (!isDouble(heightRate.toString())) || ((widthRate == 0 || widthRate > 1) || (heightRate == 0 || heightRate > 1)))) {
            return R.reError("缩放比例应为大于0并且小于等于1的小数！");
        }
        List<String> imgUrl = new ArrayList<String>();
        for (MultipartFile file : files) {
            if (checkImgType(file.getOriginalFilename())) {
                try {
                    Map<String, Object> map = saveFileBycompressed(file, configParamUtil.getPrototypeImg());
                    imgUrl.add(map.get("imgUrl").toString());
                    //获取源文件名称
                    System.out.println("Filename = "+file.getOriginalFilename());
                    File compressPic = new File(map.get("imgRealUrl").toString());
                    ImageUtil imageUtil = new ImageUtil(file.getInputStream(), compressPic,map.get("imgRealUrl").toString());
                    Image img = ImageIO.read(file.getInputStream());
                    if (null == widthRate && null == heightRate) {
                        imageUtil.resize((int) ((BufferedImage) img).getWidth(), (int) ((BufferedImage) img).getHeight());
                    }
                    if (null != widthRate && null != heightRate) {
                        imageUtil.resize((int) (((BufferedImage) img).getWidth() * widthRate), (int) (((BufferedImage) img).getHeight() * heightRate));
                    }
                    if (null == widthRate && null != heightRate) {
                        imageUtil.resizeByHeight((int) (((BufferedImage) img).getHeight() * heightRate));
                    }
                    if (null != widthRate && null == heightRate) {
                        imageUtil.resizeByWidth((int) (((BufferedImage) img).getWidth() * widthRate));
                    }
                } catch (Exception e) {
                    log.info("图片压缩失败");
                    return R.reError("图片压缩失败！");
                }
            } else {
                return R.reError("只能上传图片格式！");
            }
        }
        return R.reOk(imgUrl);
    }


    private String saveFile(MultipartFile file , String typePath)throws IOException{
        byte[] bytes = file.getBytes();
        String newFileName = getFileType(file.getOriginalFilename());
        String appendPath = getFilesPath( typePath);
        File filepath = new File(configParamUtil.getUploadFilePath() + appendPath);
        if ( !filepath.exists() ) { //如果不存在则创建
            filepath.mkdirs();
        }
        Path path = Paths.get(configParamUtil.getUploadFilePath() + appendPath + newFileName);
        Files.write(path, bytes);
        return configParamUtil.getImageUrlHead() + appendPath + newFileName;
    }


    /**
     * 保存缩略图图片
     *
     * @param file
     * @param typePath
     * @return
     * @throws IOException
     */
    private Map saveFileBycompressed(MultipartFile file, String typePath) throws IOException {
        Map<String, Object> map = new HashMap<String, Object>();
        byte[] bytes = file.getBytes();
        String newFileName = getFileType(file.getOriginalFilename());
        String appendPath = getFilesPath(typePath);
        File filepath = new File(configParamUtil.getUploadFilePath() + appendPath);
        File fileCompressedPath = new File(configParamUtil.getUploadFilePath() + appendPath + configParamUtil.getCompressed());
        if (!filepath.exists()) { //如果不存在则创建
            filepath.mkdirs();
        }
        if (!fileCompressedPath.exists()) { //如果不存在则创建
            fileCompressedPath.mkdirs();
        }
        Path path = Paths.get(configParamUtil.getUploadFilePath() + appendPath + newFileName);
        Files.write(path, bytes);
        Path pathCompressed = Paths.get(configParamUtil.getUploadFilePath() + appendPath + configParamUtil.getCompressed() + newFileName);
        System.out.println("地址" + pathCompressed);
        Files.write(pathCompressed, bytes);
        map.put("imgUrl", configParamUtil.getImageUrlHead() + appendPath +configParamUtil.getCompressed()+ newFileName);
        map.put("imgRealUrl", configParamUtil.getUploadFilePath() + appendPath + configParamUtil.getCompressed() + newFileName);
        return map;
    }

    /**
     * 获取文件名
     * @param fileName
     * @return
     */
    private String getFileType(String fileName) {
        if(fileName!=null && fileName.indexOf(".")>=0) {
            return UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf("."), fileName.length());
        }
        return "";
    }

    /**
     * 添加上传文件目录
     * @param typePath
     * @return
     */
    private String getFilesPath(String typePath){
        StringBuilder path = new StringBuilder("/uploadFile");
        if(StringUtil.isNullOrEmpty(typePath)){
            path.append("/uploads");
        }else {
            path.append("/" + typePath);
        }
        String datePath = DATE_FORMAT.format(new Date());
        path = path.append("/" +datePath);
        path = path.append("/");
        return path.toString();
    }


    /**
     * 判断文件是否为图片格式
     *
     * @param fileName
     * @return
     * @changgang
     */
    private Boolean checkImgType(String fileName) {
        if ((null != fileName) && (fileName.length() > 0)) {
            int dot = fileName.lastIndexOf(".");
            if ((dot > -1) && (dot < fileName.length() - 1)) {
                if (Arrays.asList(IMGTYPE).contains(fileName.substring(dot + 1))) {
                    return true;
                }
            }
        }
        return false;
    }

    ;

    /**
     * 判断是否为double类型
     *
     * @param str
     * @return
     */
    private boolean isDouble(String str) {
        return Pattern.compile("(0)(\\.[\\d]+)?").matcher(str).matches();
    }


}
